﻿package zf.display.tools
{
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.system.*;
	import flash.text.*;
	import flash.utils.*;

	/**
	 * FPS测算器 
	 * @author mike.zhang
	 * @langversion 3.0 
	 * @playerversion Flash 9 
	 */
	public class FPS extends Sprite
	{
		private var currentY:int;
		private var diagramTimer:int;
		private var tfTimer:int;
		private var mem:TextField;
		private var diagram:BitmapData;
		private var skins:int=-1;
		private var fps:TextField;
		private var minFps:TextField;
		private var timeTxt:TextField;
		private var minfpsNum:Number=Number.MAX_VALUE;
		private var max:TextField;
		private var maxNum:Number=0;
		private var tfDelay:int=0;
		private var skinsChanged:int=0;
		static private  const maxMemory:uint=4.1943e+007;
		static private  const diagramWidth:uint=80;
		static private  const tfDelayMax:int=10;
		//static private  var instance:FPS;
		static private  const diagramHeight:uint=30;
		
		private var bgColor:uint=0x60FFFFFF;
		private var showChart:Boolean;
		private var bgMc:Sprite;

		/**
		 * 创建一个FPS测算器,单例模式 
		 * 
		 */
		public function FPS (chart:Boolean=false)
		{
			showChart=chart;
			addEventListener (Event.ADDED_TO_STAGE,run);
			//this.addEventListener(Event.ENTER_FRAME,onInitEvent);
			//instance=this;
		}
		
		/*
		private function onInitEvent(e:Event):void
		{
			if(this.stage)
			{
				trace(this.stage);
				this.removeEventListener(Event.ENTER_FRAME,onInitEvent);
				run();
			}
		}
		*/
		private function run (e:Event=null):void
		{
			var bm:Bitmap;
			fps=new TextField  ;
			minFps=new TextField;
			timeTxt=new TextField();
			mem=new TextField  ;
			max=new TextField	;
			
			bgMc=new Sprite();
			this.addChild(bgMc);
			var mc:Sprite=new Sprite();
			this.addChild(mc);
			
			var sy:Number=0;
			//if (instance == null)
			{
				//instance=this;
				mouseEnabled=false;
				mouseChildren=false;
				fps.defaultTextFormat=new TextFormat("Tahoma",10,0xCCCCCC);
				fps.autoSize=TextFieldAutoSize.LEFT;
				fps.text="FPS:  " + Number(stage.frameRate).toFixed(2);
				fps.selectable=false;
				fps.x=- diagramWidth - 2;
				fps.y=sy;
				sy+=10;
				mc.addChild (fps);
				
				minFps.defaultTextFormat=new TextFormat("Tahoma",10,0xCCCCCC);
				minFps.autoSize=TextFieldAutoSize.LEFT;
				minFps.text="MIN:  " + Number(stage.frameRate).toFixed(2);
				minFps.selectable=false;
				minFps.x=- diagramWidth - 2;
				minFps.y=sy;
				sy+=10;
				mc.addChild (minFps);
				
				timeTxt.defaultTextFormat=new TextFormat("Tahoma",10,0x66FF33);
				timeTxt.autoSize=TextFieldAutoSize.LEFT;
				timeTxt.text="TIME: " + getOutTime();
				timeTxt.selectable=false;
				timeTxt.x=- diagramWidth - 2;
				timeTxt.y=sy;
				sy+=10;
				mc.addChild (timeTxt);
				
				maxNum=System.totalMemory;
				
				mem.defaultTextFormat=new TextFormat("Tahoma",10,0xCCCC00);
				mem.autoSize=TextFieldAutoSize.LEFT;
				mem.text="MEM: " + bytesToString(maxNum);
				mem.selectable=false;
				mem.x=- diagramWidth - 2;
				mem.y=sy;
				sy+=10;
				mc.addChild (mem);
				max.defaultTextFormat=new TextFormat("Tahoma",10,0xCCCC00);
				max.autoSize=TextFieldAutoSize.LEFT;
				max.text="MAX: " + bytesToString(maxNum);
				max.selectable=false;
				max.x=- diagramWidth - 2;
				max.y=sy;
				sy+=10;
				mc.addChild (max);
				if(showChart)
				{
					currentY=sy;
					diagram=new BitmapData(diagramWidth,diagramHeight,true,bgColor);
					bm=new Bitmap(diagram);
					bm.y=currentY + 4;
					bm.x=- diagramWidth;
					mc.addChildAt (bm,0);
				}
				addEventListener (Event.ENTER_FRAME,onEnterFrame);
				stage.addEventListener (Event.RESIZE,onResize);
				onResize ();
				diagramTimer=getTimer();
				tfTimer=diagramTimer;
			}
			bgMc.graphics.beginFill(0,0.7);
			//bgMc.graphics.drawRect(-diagramWidth,0,mc.width,mc.height);
			bgMc.graphics.drawRect(-diagramWidth,0,diagramWidth,mc.height);
			bgMc.graphics.endFill();
		}
		private function bytesToString (v:uint):String
		{
			var s:String;
			if (v < 1024)
			{
				s=String(v) + "b";
			}
			else if (v < 10240)
			{
				s=Number(v / 1024).toFixed(2) + "kb";
			}
			else if (v < 102400)
			{
				s=Number(v / 1024).toFixed(1) + "kb";
			}
			else if (v < 1048576)
			{
				s=Math.round(v / 1024) + "kb";
			}
			else if (v < 10485760)
			{
				s=Number(v / 1048576).toFixed(2) + "mb";
			}
			else if (v < 104857600)
			{
				s=Number(v / 1048576).toFixed(1) + "mb";
			}
			else
			{
				s=Math.round(v / 1048576) + "mb";
			}
			return s;
		}

		private function onEnterFrame (e:Event):void
		{
			tfDelay++;
			var thisTime:Number=getTimer();
			var f:Number;
			if (tfDelay >= tfDelayMax)
			{
				f=1000 * tfDelayMax / (thisTime - tfTimer);
				tfDelay=0;
				fps.text="FPS:  " + f.toFixed(2);
				tfTimer=thisTime;
				
				if(f<minfpsNum)
				{
					minfpsNum=f;
					minFps.text="MIN:  " + minfpsNum.toFixed(2);
				}
			}
			timeTxt.text="TIME: " + getOutTime();
			
			var num:Number=System.totalMemory;
			mem.text="MEM: " + bytesToString(num);
			if(num>maxNum)
			{
				maxNum=num;
				max.text="MAX: " + bytesToString(num);
			}
			if(!showChart)
			{
				return;
			}
			var time:Number=1000 / (thisTime - diagramTimer);
			var bl:Number =time > stage.frameRate?(1):(time / stage.frameRate);
			diagramTimer=thisTime;
			diagram.scroll (1,0);
			diagram.fillRect (new Rectangle(0,0,1,diagram.height),bgColor);
			diagram.setPixel32 (0,diagramHeight * (1 - bl),0xFFCCCCCC);
			var skinsBL:Number=skins == 0?0:skinsChanged / skins;
			diagram.setPixel32 (0,diagramHeight * (1 - skinsBL),0xFFFF6600);
			var MBL:Number=System.totalMemory / maxMemory;
			diagram.setPixel32 (0,diagramHeight * (1 - MBL),0xFFCCCC00);
			
			return;
		}

		private function onResize (e:Event=null):void
		{
			var p:Point=parent.globalToLocal(new Point(stage.stageWidth - 2,-3));
			x=p.x;
			y=p.y;
			return;
		}
		
		private function getOutTime():String
		{
			var num:uint=Math.round(flash.utils.getTimer()/1000);
			
			var f:uint=Math.floor(num/60);
			var str:String="";
			if(f>0)
			{
				str+=f+":";
			}
			var s:Number=num%60
			var ss:String=s>9?s+"":"0"+s;
			str+=ss;
			return str;
		}
	}
}